package com.aizuda.boot.modules.business.negotiation.aspect;

import com.aizuda.boot.modules.common.constant.enums.NegotiationNodeStatusEnum;
import com.aizuda.boot.modules.common.constant.enums.NegotiationStatusEnum;
import com.aizuda.boot.modules.business.negotiation.annotation.CreateNegotiationData;
import com.aizuda.boot.modules.business.negotiation.entity.*;
import com.aizuda.boot.modules.business.negotiation.mapper.*;
import com.aizuda.boot.modules.business.contract_operation_log.service.ContractOperationLogService;
import com.aizuda.boot.modules.business.contract_operation_log.domain.entity.ContractOperationLog;
import com.aizuda.boot.modules.common.constant.enums.WorkFlowTypeEnums;
import com.aizuda.boot.modules.common.constant.enums.ActionTypeEnums;
import com.aizuda.boot.modules.common.constant.enums.SourceTypeEnums;
import com.aizuda.boot.modules.business.contract.mapper.ContractMapper;
import com.aizuda.boot.modules.business.contract.mapper.ContractFieldValueMapper;
import com.aizuda.boot.modules.business.contract.entity.ContractFieldValueEntity;
import com.aizuda.boot.modules.file.service.IContractFileService;
import com.aizuda.boot.modules.file.domain.entity.ContractFileEntity;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.aizuda.boot.modules.flw.entity.dto.ProcessStartDTO;
import com.aizuda.bpm.engine.FlowLongEngine;
import com.aizuda.bpm.engine.entity.FlwProcess;
import com.aizuda.bpm.engine.entity.FlwTask;
import com.aizuda.bpm.engine.model.*;
import com.aizuda.common.toolkit.JacksonUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * 基于注解的协商数据创建AOP切面
 */
@Aspect
@Component
@Slf4j
public class NegotiationDataAspect {
    
    @Resource
    private ContractNegotiationInstanceMapper negotiationInstanceMapper;
    
    @Resource
    private ContractNegotiationNodeInstanceMapper nodeInstanceMapper;
    
    @Resource
    private ContractNegotiationParticipantMapper participantMapper;
    
    @Resource
    private FlowLongEngine flowLongEngine;
    
    @Resource
    private ContractOperationLogService contractOperationLogService;
    
    @Resource
    private ContractMapper contractMapper;
    
    @Resource
    private ContractFieldValueMapper contractFieldValueMapper;
    
    @Resource
    private IContractFileService contractFileService;
    
    private final ExpressionParser parser = new SpelExpressionParser();
    
    // 用于存储当前处理的上下文，以便在其他方法中访问
    private ThreadLocal<StandardEvaluationContext> currentContext = new ThreadLocal<>();
    
    /**
     * 拦截带有@CreateNegotiationData注解的方法
     */
    @AfterReturning(
        pointcut = "@annotation(createNegotiationData)",
        returning = "result"
    )
//    @Transactional
    public void afterMethodWithAnnotation(JoinPoint joinPoint, CreateNegotiationData createNegotiationData, Object result) {
        try {
            if (!createNegotiationData.enabled()) {
                log.debug("CreateNegotiationData注解已禁用");
                return;
            }
            
            // 创建SpEL上下文
            StandardEvaluationContext context = createEvaluationContext(joinPoint, result);
            currentContext.set(context); // 设置到ThreadLocal中供其他方法使用
            
            // 解析合同ID
            Integer contractId = parseContractId(createNegotiationData.contractIdSource(), context);
            if (contractId == null) {
                log.warn("无法解析合同ID，表达式: {}", createNegotiationData.contractIdSource());
                return;
            }
            
            // 解析申请人ID
            Long applicantId = parseApplicantId(createNegotiationData.applicantIdSource(), context);
            if (applicantId == null) {
                log.warn("无法解析申请人ID，表达式: {}", createNegotiationData.applicantIdSource());
                return;
            }
            
            // 解析流程ID
            Long processId = parseProcessId(context);
            if (processId != null) {
                createNegotiationData(contractId, applicantId, processId);
                log.info("成功创建协商数据 - 合同ID: {}, 申请人ID: {}, 流程ID: {}", 
                        contractId, applicantId, processId);
            } else {
                log.warn("无法获取流程ID，跳过协商数据创建");
            }
            
        } catch (Exception e) {
            log.error("基于注解创建协商数据失败", e);
        } finally {
            // 清理ThreadLocal，避免内存泄漏
            currentContext.remove();
        }
    }
    
    /**
     * 创建SpEL表达式解析上下文
     */
    private StandardEvaluationContext createEvaluationContext(JoinPoint joinPoint, Object result) {
        StandardEvaluationContext context = new StandardEvaluationContext();
        
        // 设置方法参数
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Parameter[] parameters = method.getParameters();
        Object[] args = joinPoint.getArgs();
        
        for (int i = 0; i < parameters.length && i < args.length; i++) {
            context.setVariable(parameters[i].getName(), args[i]);
            // 添加按位置的参数访问
            context.setVariable("p" + i, args[i]);
            // 常用参数名映射
            if (i == 0) {
                context.setVariable("dto", args[i]);
            }
        }
        
        // 设置返回值
        context.setVariable("result", result);
        context.setVariable("target", joinPoint.getTarget());
        
        return context;
    }
    
    /**
     * 解析合同ID
     */
    private Integer parseContractId(String expression, StandardEvaluationContext context) {
        try {
            Object value = parser.parseExpression(expression).getValue(context);
            if (value != null) {
                if (value instanceof Number) {
                    return ((Number) value).intValue();
                } else if (value instanceof String) {
                    String strValue = (String) value;
                    if (strValue.startsWith("CONTRACT_")) {
                        return Integer.parseInt(strValue.substring(9));
                    }
                    return Integer.parseInt(strValue);
                }
            }
        } catch (Exception e) {
            log.error("解析合同ID失败，表达式: {}", expression, e);
        }
        return null;
    }
    
    /**
     * 解析申请人ID
     */
    private Long parseApplicantId(String expression, StandardEvaluationContext context) {
        try {
            Object value = parser.parseExpression(expression).getValue(context);
            if (value != null) {
                if (value instanceof Number) {
                    return ((Number) value).longValue();
                } else if (value instanceof String) {
                    return Long.parseLong((String) value);
                }
            }
        } catch (Exception e) {
            log.error("解析申请人ID失败，表达式: {}", expression, e);
        }
        return null;
    }
    
    /**
     * 解析流程ID
     */
    private Long parseProcessId(StandardEvaluationContext context) {
        try {
            // 优先从DTO中获取流程定义ID
            Object dto = context.lookupVariable("dto");
            if (dto instanceof ProcessStartDTO) {
                ProcessStartDTO processStartDTO = (ProcessStartDTO) dto;
                Long processDefId = processStartDTO.getProcessId();
                log.info("从DTO中获取流程定义ID: {}", processDefId);
                return processDefId;
            }
            
            // 如果DTO中没有，再尝试其他方式（但通常不应该走到这里）
            log.warn("无法从DTO中获取流程定义ID，dto类型: {}", dto != null ? dto.getClass().getName() : "null");
            
            // 注意：不要从返回值获取，因为返回值是流程实例ID，不是流程定义ID
            
            return null;
        } catch (Exception e) {
            log.error("解析流程定义ID失败", e);
            return null;
        }
    }
    
    /**
     * 从当前上下文中获取assigneeMap
     * 使用和launchProcess方法相同的逻辑：final Map<String, DynamicAssignee> assigneeMap = dto.getAssigneeMap();
     */
    @SuppressWarnings("unchecked")
    private Map<String, Object> getAssigneeMapFromContext() {
        try {
            StandardEvaluationContext context = currentContext.get();
            if (context == null) {
                log.warn("当前上下文为空，无法获取assigneeMap");
                return Collections.emptyMap();
            }
            
            // 使用和launchProcess相同的方式：从DTO中获取assigneeMap
            Object dto = context.lookupVariable("dto");
            log.info("从上下文获取dto对象: {}", dto != null ? dto.getClass().getSimpleName() : "null");
            
            if (dto != null && dto instanceof ProcessStartDTO) {
                // 直接使用ProcessStartDTO的getAssigneeMap方法，和launchProcess一样
                ProcessStartDTO processStartDTO = (ProcessStartDTO) dto;
                Map<String, DynamicAssignee> originalAssigneeMap = processStartDTO.getAssigneeMap();
                
                if (originalAssigneeMap != null && !originalAssigneeMap.isEmpty()) {
                    log.info("成功获取DynamicAssignee类型的assigneeMap，包含 {} 个节点: {}", 
                            originalAssigneeMap.size(), originalAssigneeMap.keySet());
                    
                    // 转换为我们的处理格式
                    Map<String, Object> assigneeMap = new HashMap<>();
                    for (Map.Entry<String, DynamicAssignee> entry : originalAssigneeMap.entrySet()) {
                        assigneeMap.put(entry.getKey(), entry.getValue());
                        log.debug("添加节点Key: {} 到assigneeMap", entry.getKey());
                    }
                    return assigneeMap;
                } else {
                    log.info("DTO中的assigneeMap为空");
                }
            } else {
                log.warn("dto对象不是ProcessStartDTO类型: {}", dto != null ? dto.getClass().getName() : "null");
                
                // 回退到反射方式（兼容其他DTO类型）
                if (dto != null) {
                    try {
                        Method getAssigneeMapMethod = dto.getClass().getMethod("getAssigneeMap");
                        Object assigneeMapObj = getAssigneeMapMethod.invoke(dto);
                        log.info("通过反射获取到assigneeMapObj: {}", assigneeMapObj != null ? assigneeMapObj.getClass().getSimpleName() : "null");
                        
                        if (assigneeMapObj instanceof Map) {
                            Map<String, Object> assigneeMap = (Map<String, Object>) assigneeMapObj;
                            log.info("成功获取assigneeMap，包含 {} 个节点的审批人配置: {}", assigneeMap.size(), assigneeMap.keySet());
                            return assigneeMap;
                        } else {
                            log.warn("assigneeMapObj不是Map类型: {}", assigneeMapObj);
                        }
                    } catch (Exception e) {
                        log.error("从DTO获取assigneeMap失败: {}", e.getMessage(), e);
                    }
                }
            }
            
            log.debug("未找到assigneeMap数据");
            return Collections.emptyMap();
            
        } catch (Exception e) {
            log.error("获取assigneeMap失败", e);
            return Collections.emptyMap();
        }
    }
    
    /**
     * 创建协商相关数据
     */
    private void createNegotiationData(Integer contractId, Long applicantId, Long processDefId) {
        log.info("开始创建协商数据 - 合同ID: {}, 申请人ID: {}, 流程定义ID: {}", contractId, applicantId, processDefId);

        // 获取流程实例ID（从返回值中获取）
        Long instanceId = null;
        try {
            Object result = currentContext.get().lookupVariable("result");
            log.info("从上下文获取的result对象: {}, 类型: {}", result, result != null ? result.getClass().getName() : "null");
            if (result instanceof Long) {
                instanceId = (Long) result;
                log.info("成功获取流程实例ID: {}", instanceId);
            } else {
                log.warn("result不是Long类型，无法获取流程实例ID");
            }
        } catch (Exception e) {
            log.error("获取流程实例ID失败", e);
        }

        // 创建协商实例（增加流程实例ID的保存）
        ContractNegotiationInstanceEntity instance = createNegotiationInstance(contractId, applicantId, instanceId);
        log.info("创建协商实例成功 - 实例ID: {}, 流程实例ID: {}", instance.getId(), instanceId);

        // 同步处理流程解析和节点创建（改为同步执行，避免事务问题）
        try {
            // 获取流程定义（使用传入的流程定义ID，而不是流程实例ID）
            FlwProcess flwProcess = flowLongEngine.processService().getProcessById(processDefId);
            if (flwProcess == null) {
                log.error("流程定义不存在: {}", processDefId);
                return;
            }

            // 解析流程模型
            ProcessModel processModel = ModelHelper.buildProcessModel(flwProcess.getModelContent());
            NodeModel rootNode = processModel.getNodeConfig();

            // 获取assigneeMap（动态分配的审批人信息）
            Map<String, Object> assigneeMap = getAssigneeMapFromContext();
            log.info("获取到assigneeMap，包含 {} 个节点的审批人配置", assigneeMap.size());

            // 获取所有审批节点（结合assigneeMap获取实际参与者）
            List<NodeInfo> nodeInfos = extractApprovalNodes(rootNode, assigneeMap);
            log.info("解析到 {} 个审批节点", nodeInfos.size());

            // 创建节点实例
            List<ContractNegotiationNodeInstanceEntity> nodeInstances =
                createNodeInstances(instance.getId(), nodeInfos);
            log.info("创建了 {} 个节点实例", nodeInstances.size());

            // 创建参与者
            createParticipants(instance.getId(), nodeInstances, nodeInfos);

            // 记录发起协商日志
            logNegotiationLaunch(contractId, applicantId, instanceId);

            // 记录邀请协商者日志（获取所有参与者ID）
            Set<Long> participantIds = extractAllParticipantIds(nodeInfos);
            logNegotiatorInvitation(contractId, participantIds);

            // 如果有流程实例ID，获取第一个任务并更新节点实例
            if (instanceId != null) {
                log.info("准备更新任务信息，流程实例ID: {}", instanceId);
                updateFirstTaskInfo(instanceId, nodeInstances);
            } else {
                log.warn("没有流程实例ID，跳过任务信息更新");
            }

            log.info("协商数据创建完成 - 协商实例ID: {}, 节点数: {}", instance.getId(), nodeInstances.size());
        } catch (Exception e) {
            log.error("创建协商节点和参与者失败 - 协商实例ID: {}", instance.getId(), e);
        }
    }
    
    /**
     * 更新第一个任务的信息（优化版本）
     */
    private void updateFirstTaskInfo(Long instanceId, List<ContractNegotiationNodeInstanceEntity> nodeInstances) {
        try {
            log.info("开始更新任务信息 - 流程实例ID: {}", instanceId);

            // 尝试立即获取任务，如果获取不到就异步处理，不阻塞主流程
            List<FlwTask> tasks = flowLongEngine.queryService().getTasksByInstanceId(instanceId);

            if (tasks != null && !tasks.isEmpty()) {
                log.info("立即获取到 {} 个任务，流程实例ID: {}", tasks.size(), instanceId);
                FlwTask firstTask = tasks.get(0);

                // 更新第一个节点实例的任务信息
                if (nodeInstances != null && !nodeInstances.isEmpty()) {
                    updateNodeWithTaskInfo(nodeInstances.get(0), firstTask);
                }
            } else {
                log.info("任务尚未创建，将异步更新任务信息，流程实例ID: {}", instanceId);
                // 异步重试，不阻塞主流程
                asyncRetryUpdateTaskInfo(instanceId, nodeInstances);
            }
        } catch (Exception e) {
            log.error("更新任务信息失败，流程实例ID: {}", instanceId, e);
        }
    }



    /**
     * 更新节点的任务信息
     */
    private void updateNodeWithTaskInfo(ContractNegotiationNodeInstanceEntity node, FlwTask task) {
        try {
            // 在节点实例中保存任务ID
            node.setTaskId(task.getId());

            // 同时在ruleConfigSnapshot中保存更多任务信息
            Map<String, Object> taskInfo = new HashMap<>();
            taskInfo.put("taskId", task.getId());
            taskInfo.put("taskKey", task.getTaskKey());
            taskInfo.put("taskName", task.getTaskName());
            node.setRuleConfigSnapshot(JacksonUtils.toJson(taskInfo));

            nodeInstanceMapper.updateById(node);

            log.info("成功更新协商节点任务信息 - 节点ID: {}, 任务ID: {}", node.getId(), task.getId());
        } catch (Exception e) {
            log.error("更新节点任务信息失败 - 节点ID: {}, 任务ID: {}", node.getId(), task.getId(), e);
        }
    }

    /**
     * 异步重试更新任务信息（改进版本）
     */
    private void asyncRetryUpdateTaskInfo(Long instanceId, List<ContractNegotiationNodeInstanceEntity> nodeInstances) {
        CompletableFuture.runAsync(() -> {
            try {
                // 异步重试，最多重试3次，每次间隔200ms
                List<FlwTask> tasks = null;
                for (int i = 0; i < 3; i++) {
                    try {
                        Thread.sleep(200 * (i + 1)); // 递增延迟：200ms, 400ms, 600ms
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        return;
                    }

                    tasks = flowLongEngine.queryService().getTasksByInstanceId(instanceId);
                    if (tasks != null && !tasks.isEmpty()) {
                        break;
                    }
                }

                if (tasks != null && !tasks.isEmpty() && nodeInstances != null && !nodeInstances.isEmpty()) {
                    FlwTask firstTask = tasks.get(0);
                    updateNodeWithTaskInfo(nodeInstances.get(0), firstTask);
                    log.info("异步更新任务信息成功 - 流程实例ID: {}, 任务ID: {}", instanceId, firstTask.getId());
                } else {
                    log.warn("异步重试仍无法获取任务信息 - 流程实例ID: {}", instanceId);
                }
            } catch (Exception e) {
                log.error("异步更新任务信息失败 - 流程实例ID: {}", instanceId, e);
            }
        });
    }

    /**
     * 异步执行日志记录操作
     */
    private void executeAsyncLogOperations(Integer contractId, Long applicantId, Long instanceId) {
        CompletableFuture.runAsync(() -> {
            try {
                // 记录发起协商日志
                logNegotiationLaunch(contractId, applicantId, instanceId);
            } catch (Exception e) {
                log.error("异步日志记录失败 - 合同ID: {}", contractId, e);
            }
        });
    }
    
    // 修改创建协商实例方法，增加流程实例ID参数
    private ContractNegotiationInstanceEntity createNegotiationInstance(Integer contractId, Long applicantId, Long instanceId) {
        // 先查找是否已存在协商实例
        ContractNegotiationInstanceEntity existingInstance = negotiationInstanceMapper.selectOne(
                new LambdaQueryWrapper<ContractNegotiationInstanceEntity>()
                        .eq(ContractNegotiationInstanceEntity::getContractId, contractId)
                        .in(ContractNegotiationInstanceEntity::getNegotiationStatus,
                            Arrays.asList(
                                NegotiationStatusEnum.PENDING_NEGOTIATION.getCode(),
                                NegotiationStatusEnum.IN_NEGOTIATION.getCode()
                            ))
                        .orderByDesc(ContractNegotiationInstanceEntity::getCreatedAt)
                        .last("LIMIT 1")
        );

        if (existingInstance != null) {
            // 更新已存在的实例
            log.info("找到已存在的协商实例，更新状态和流程实例ID - 实例ID: {}, 合同ID: {}", existingInstance.getId(), contractId);

            // 清理旧的节点实例和参与者数据
            cleanupOldNegotiationData(existingInstance.getId());

            existingInstance.setNegotiationStatus(NegotiationStatusEnum.IN_NEGOTIATION.getCode())  // 修改状态为协商中
                    .setProcessInstanceId(instanceId)  // 设置流程实例ID
                    .setUpdatedAt(LocalDateTime.now());

            negotiationInstanceMapper.updateById(existingInstance);
            return existingInstance;
        } else {
            // 创建新的协商实例
            log.info("未找到已存在的协商实例，创建新实例 - 合同ID: {}", contractId);
            ContractNegotiationInstanceEntity instance = new ContractNegotiationInstanceEntity()
                    .setContractId(contractId)
                    .setConfigId(1)
                    .setNegotiationStage("发起合同申请")
                    .setNegotiationStatus(NegotiationStatusEnum.IN_NEGOTIATION.getCode())  // 直接设置为协商中状态
                    .setStartTime(LocalDateTime.now())
                    .setApplicantId(applicantId)
                    .setProcessInstanceId(instanceId)  // 使用新的字段保存流程实例ID
                    .setCreatedAt(LocalDateTime.now())
                    .setUpdatedAt(LocalDateTime.now());

            negotiationInstanceMapper.insert(instance);
            return instance;
        }
    }

    /**
     * 清理旧的协商数据（节点实例和参与者）
     */
    private void cleanupOldNegotiationData(Integer instanceId) {
        try {
            log.info("开始清理协商实例的旧数据 - 实例ID: {}", instanceId);

            // 1. 删除旧的参与者数据
            int deletedParticipants = participantMapper.delete(
                    new LambdaQueryWrapper<ContractNegotiationParticipantEntity>()
                            .eq(ContractNegotiationParticipantEntity::getInstanceId, instanceId)
            );
            log.info("删除了 {} 条旧的参与者记录", deletedParticipants);

            // 2. 删除旧的节点实例数据
            int deletedNodes = nodeInstanceMapper.delete(
                    new LambdaQueryWrapper<ContractNegotiationNodeInstanceEntity>()
                            .eq(ContractNegotiationNodeInstanceEntity::getInstanceId, instanceId)
            );
            log.info("删除了 {} 条旧的节点实例记录", deletedNodes);

            log.info("协商实例旧数据清理完成 - 实例ID: {}", instanceId);

        } catch (Exception e) {
            log.error("清理协商实例旧数据失败 - 实例ID: {}", instanceId, e);
            throw new RuntimeException("清理旧协商数据失败", e);
        }
    }

    private List<NodeInfo> extractApprovalNodes(NodeModel rootNode, Map<String, Object> assigneeMap) {
        List<NodeInfo> nodeInfos = new ArrayList<>();
        collectApprovalNodes(rootNode, nodeInfos, 1, assigneeMap);
        return nodeInfos;
    }
    
    private void collectApprovalNodes(NodeModel node, List<NodeInfo> nodeInfos, int currentOrder, Map<String, Object> assigneeMap) {
        if (node == null) return;
        
        if (isApprovalNode(node)) {
            NodeInfo nodeInfo = new NodeInfo();
            nodeInfo.setOrder(currentOrder);
            nodeInfo.setRoleId(generateNodeRoleId(node, currentOrder));
            nodeInfo.setNodeKey(node.getNodeKey());
            nodeInfo.setNodeName(node.getNodeName());
            nodeInfo.setUserIds(extractUserIds(node, assigneeMap));
            nodeInfos.add(nodeInfo);
            currentOrder++;
        }
        
        // 只处理基本的子节点遍历，后续可以根据需要添加条件分支处理
        if (node.getChildNode() != null) {
            collectApprovalNodes(node.getChildNode(), nodeInfos, currentOrder, assigneeMap);
        }
    }
    
    private boolean isApprovalNode(NodeModel node) {
        return node.getType() != null && node.getType() == 1;
    }
    
    /**
     * 为审批流节点生成在协商系统中的节点标识ID
     * 这个ID在协商系统中被当作"roleId"，但实际表示的是审批节点
     */
    private Integer generateNodeRoleId(NodeModel node, int order) {
        // 方案1：使用节点Key的hash值
        if (node.getNodeKey() != null) {
            return Math.abs(node.getNodeKey().hashCode()) % 100000;
        }
        
        // 方案2：使用节点名称的hash值
        if (node.getNodeName() != null) {
            return Math.abs(node.getNodeName().hashCode()) % 100000;
        }
        
        // 方案3：使用顺序号生成（简单但可能冲突）
        return 1000 + order;
    }
    
    /**
     * 从节点模型和assigneeMap中提取用户ID列表
     * 优先从assigneeMap获取动态分配的审批人，如果没有则从节点静态配置获取
     */
    @SuppressWarnings("unchecked")
    private List<Long> extractUserIds(NodeModel nodeModel, Map<String, Object> assigneeMap) {
        List<Long> userIds = new ArrayList<>();
        String nodeKey = nodeModel.getNodeKey();
        String nodeName = nodeModel.getNodeName();

        log.info("开始解析节点用户ID - 节点名称: {}, 节点Key: {}", nodeName, nodeKey);

        // 首先尝试从assigneeMap获取动态分配的审批人
        if (assigneeMap != null && assigneeMap.containsKey(nodeKey)) {
            Object assigneeObj = assigneeMap.get(nodeKey);
            log.info("从assigneeMap找到节点 {} 的审批人配置，类型: {}", nodeKey, 
                    assigneeObj != null ? assigneeObj.getClass().getSimpleName() : "null");
            
            try {
                // assigneeObj 可能是 DynamicAssignee 对象或者 Map
                if (assigneeObj instanceof DynamicAssignee) {
                    // 处理 DynamicAssignee 对象
                    DynamicAssignee dynamicAssignee = (DynamicAssignee) assigneeObj;
                    List<NodeAssignee> assigneeList = dynamicAssignee.getAssigneeList();

                    if (assigneeList != null && !assigneeList.isEmpty()) {
                        for (NodeAssignee assignee : assigneeList) {
                            try {
                                Long userId = Long.parseLong(assignee.getId());
                                userIds.add(userId);
                                log.debug("添加审批人: {} - {} (来自DynamicAssignee)", userId, assignee.getName());
                            } catch (NumberFormatException e) {
                                log.error("DynamicAssignee中用户ID格式错误: {}", assignee.getId());
                            }
                        }
                    }
                } else if (assigneeObj instanceof Map) {
                    // 处理 Map 对象（JSON反序列化后的格式）
                    Map<String, Object> dynamicAssignee = (Map<String, Object>) assigneeObj;

                    // 获取assigneeList
                    Object assigneeListObj = dynamicAssignee.get("assigneeList");
                    if (assigneeListObj instanceof List) {
                        List<Map<String, Object>> assigneeList = (List<Map<String, Object>>) assigneeListObj;

                        for (Map<String, Object> assignee : assigneeList) {
                            Object idObj = assignee.get("id");
                            Object nameObj = assignee.get("name");
                            if (idObj != null) {
                                try {
                                    Long userId = Long.parseLong(idObj.toString());
                                    userIds.add(userId);
                                    log.debug("添加审批人: {} - {} (来自Map)", userId, nameObj);
                                } catch (NumberFormatException e) {
                                    log.error("Map中用户ID格式错误: {}", idObj);
                                }
                            }
                        }
                    }
                } else {
                    log.warn("assigneeObj类型不支持: {}", assigneeObj.getClass().getName());
                }

                if (!userIds.isEmpty()) {
                    log.info("从assigneeMap成功获取节点 {} 的 {} 个审批人", nodeName, userIds.size());
                    return userIds; // 如果从assigneeMap获取到了用户，直接返回
                }

            } catch (Exception e) {
                log.error("解析assigneeMap中节点 {} 的审批人信息失败", nodeKey, e);
            }
        } else {
            log.info("assigneeMap中未找到节点 {} 的配置，assigneeMap为空: {}, assigneeMap大小: {}", 
                    nodeKey, assigneeMap == null, assigneeMap == null ? 0 : assigneeMap.size());
        }

        // 如果assigneeMap中没有找到或解析失败，则从节点静态配置获取
        log.info("尝试从静态配置获取节点 {} 的审批人", nodeName);
        
        if (nodeModel.getSetType() != null) {
            String setType = nodeModel.getSetType().toString();
            log.info("节点 {} 的设置类型: {}", nodeName, setType);

            switch (setType) {
                case "specifyMembers":
                    // 指定成员：直接从nodeAssigneeList获取用户ID
                    List<NodeAssignee> assigneeList = nodeModel.getNodeAssigneeList();
                    if (assigneeList != null) {
                        for (NodeAssignee assignee : assigneeList) {
                            try {
                                userIds.add(Long.parseLong(assignee.getId()));
                                log.debug("添加审批人: {} (来自静态配置)", assignee.getId());
                            } catch (NumberFormatException e) {
                                log.error("静态配置中用户ID格式错误: {}", assignee.getId());
                            }
                        }
                    }
                    break;

                case "role":
                    // 角色类型：需要根据角色ID查询用户列表
                    List<NodeAssignee> roleList = nodeModel.getNodeAssigneeList();
                    if (roleList != null && !roleList.isEmpty()) {
                        Integer roleId = Integer.parseInt(roleList.get(0).getId());
                        // TODO: 这里需要调用权限服务获取角色下的用户列表
                        // userIds.addAll(getUsersByRoleId(roleId));
                        log.info("需要根据角色ID {} 获取用户列表", roleId);
                    }
                    break;

                case "department":
                    // 部门类型：需要根据部门ID查询用户列表
                    List<NodeAssignee> deptList = nodeModel.getNodeAssigneeList();
                    if (deptList != null && !deptList.isEmpty()) {
                        Integer deptId = Integer.parseInt(deptList.get(0).getId());
                        // TODO: 这里需要调用部门服务获取部门下的用户列表
                        // userIds.addAll(getUsersByDepartmentId(deptId));
                        log.info("需要根据部门ID {} 获取用户列表", deptId);
                    }
                    break;

                case "initiatorThemselves":
                    // 发起人自己：从申请人信息获取
                    try {
                        StandardEvaluationContext context = currentContext.get();
                        if (context != null) {
                            Long applicantId = parseApplicantId("T(com.aizuda.service.web.UserSession).getLoginInfo().getUserId()", context);
                            if (applicantId != null) {
                                userIds.add(applicantId);
                                log.debug("添加发起人自己作为审批人: {}", applicantId);
                            }
                        }
                    } catch (Exception e) {
                        log.error("获取发起人ID失败", e);
                    }
                    break;

                case "supervisor":
                    // 直接主管：需要根据发起人查询其主管
                    log.info("直接主管审批，需要根据申请人查询主管信息");
                    break;

                default:
                    log.warn("未处理的节点设置类型: {}", setType);
                    break;
            }
        }

        log.info("节点 {} ({}) 最终获取到 {} 个审批人", 
                nodeName, nodeKey, userIds.size());

        // 临时调试：如果没有找到用户，添加一些测试用户
        if (userIds.isEmpty()) {
            log.warn("节点 {} 没有找到审批人，添加测试用户", nodeName);
            // 添加一些测试用户ID（请根据实际情况修改）
            userIds.add(1L); // 测试用户1
            userIds.add(2L); // 测试用户2
            log.info("添加测试用户后，节点 {} 现在有 {} 个审批人", nodeName, userIds.size());
        }

        return userIds;
    }
    
    /**
     * 创建节点实例
     * 将审批流节点映射为协商系统的节点实例
     * 第一次发起时所有节点状态都为NOT_START，不激活任何节点
     */
    private List<ContractNegotiationNodeInstanceEntity> createNodeInstances(Integer instanceId, List<NodeInfo> nodeInfos) {
        List<ContractNegotiationNodeInstanceEntity> nodeInstances = new ArrayList<>();
        
        for (NodeInfo nodeInfo : nodeInfos) {
            // 所有节点都不激活，状态为NOT_START，isCurrentNode都为false
            String status = NegotiationNodeStatusEnum.NOT_START.getCode();
            boolean isCurrentNode = false;
            
            ContractNegotiationNodeInstanceEntity nodeInstance = new ContractNegotiationNodeInstanceEntity()
                    .setInstanceId(instanceId)
                    .setRoleId(nodeInfo.getRoleId())             // 审批流节点的唯一标识
                    .setNodeName(nodeInfo.getNodeName())        // 审批流节点名称
                    .setStatus(status)                           // 所有节点都为NOT_START状态
                    .setIsCurrentNode(isCurrentNode)            // 所有节点都不是当前节点
                    .setSortOrder(nodeInfo.getOrder())          // 节点顺序
                    .setCreatedAt(LocalDateTime.now())
                    .setUpdatedAt(LocalDateTime.now());
            
            // 如果您的表结构支持，可以存储更多审批流节点信息
            // nodeInstance.setNodeKey(nodeInfo.getNodeKey());     // 审批流节点Key
            // nodeInstance.setNodeName(nodeInfo.getNodeName());   // 审批流节点名称
            
            nodeInstanceMapper.insert(nodeInstance);
            nodeInstances.add(nodeInstance);
        }
        return nodeInstances;
    }
    
    /**
     * 创建参与者（优化版本 - 批量插入）
     * 根据审批流节点的设置创建对应的协商参与者
     */
    private void createParticipants(Integer instanceId,
                                    List<ContractNegotiationNodeInstanceEntity> nodeInstances,
                                    List<NodeInfo> nodeInfos) {

        log.info("开始创建协商参与者 - 协商实例ID: {}, 节点实例数: {}, 节点信息数: {}", 
                instanceId, nodeInstances.size(), nodeInfos.size());

        List<ContractNegotiationParticipantEntity> participantsToInsert = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();

        for (int i = 0; i < nodeInstances.size() && i < nodeInfos.size(); i++) {
            ContractNegotiationNodeInstanceEntity nodeInstance = nodeInstances.get(i);
            NodeInfo nodeInfo = nodeInfos.get(i);

            log.info("处理节点 {} - 节点实例ID: {}, 用户数量: {}", 
                    nodeInfo.getNodeName(), nodeInstance.getId(), nodeInfo.getUserIds().size());

            // 如果有具体的用户ID列表
            if (!nodeInfo.getUserIds().isEmpty()) {
                for (Long userId : nodeInfo.getUserIds()) {
                    ContractNegotiationParticipantEntity participant = new ContractNegotiationParticipantEntity()
                            .setInstanceId(instanceId)
                            .setNodeInstanceId(nodeInstance.getId())
                            .setEmployeeId(userId)
                            .setParticipantType("NODE_PARTICIPANT")
                            .setIsViewed(false)
                            .setIsConfirmed(false)
                            .setCreatedAt(now)
                            .setUpdatedAt(now);

                    participantsToInsert.add(participant);
                    log.debug("准备创建参与者 - 用户ID: {}, 节点实例ID: {}", userId, nodeInstance.getId());
                }
            } else {
                log.warn("节点 {} 没有用户ID，跳过创建参与者", nodeInfo.getNodeName());
            }
        }

        log.info("准备批量插入 {} 个参与者", participantsToInsert.size());

        // 批量插入参与者
        if (!participantsToInsert.isEmpty()) {
            batchInsertParticipants(participantsToInsert);
        } else {
            log.warn("没有参与者需要插入，这可能表示所有节点都没有配置审批人");
        }
    }
    
    /**
     * 批量插入参与者
     */
    private void batchInsertParticipants(List<ContractNegotiationParticipantEntity> participants) {
        try {
            log.info("开始批量插入 {} 个参与者", participants.size());
            
            // 分批插入，每批最多1000条
            int batchSize = 1000;
            int successCount = 0;
            int failCount = 0;
            
            for (int i = 0; i < participants.size(); i += batchSize) {
                int endIndex = Math.min(i + batchSize, participants.size());
                List<ContractNegotiationParticipantEntity> batch = participants.subList(i, endIndex);
                
                log.info("插入第 {} 批，包含 {} 个参与者", (i / batchSize + 1), batch.size());

                // 使用MyBatis-Plus的批量插入
                for (ContractNegotiationParticipantEntity participant : batch) {
                    try {
                        int result = participantMapper.insert(participant);
                        if (result > 0) {
                            successCount++;
                            log.debug("成功插入参与者 - ID: {}, 用户ID: {}, 节点实例ID: {}", 
                                    participant.getId(), participant.getEmployeeId(), participant.getNodeInstanceId());
                        } else {
                            failCount++;
                            log.error("插入参与者失败 - 用户ID: {}, 节点实例ID: {}", 
                                    participant.getEmployeeId(), participant.getNodeInstanceId());
                        }
                    } catch (Exception e) {
                        failCount++;
                        log.error("插入参与者异常 - 用户ID: {}, 节点实例ID: {}", 
                                participant.getEmployeeId(), participant.getNodeInstanceId(), e);
                    }
                }
            }
            
            log.info("批量插入完成 - 成功: {}, 失败: {}", successCount, failCount);
            
        } catch (Exception e) {
            log.error("批量插入参与者失败", e);
            
            // 如果批量插入失败，回退到单条插入
            log.info("回退到单条插入模式");
            int successCount = 0;
            int failCount = 0;
            
            for (ContractNegotiationParticipantEntity participant : participants) {
                try {
                    int result = participantMapper.insert(participant);
                    if (result > 0) {
                        successCount++;
                    } else {
                        failCount++;
                    }
                } catch (Exception ex) {
                    failCount++;
                    log.error("单条插入参与者失败 - 用户ID: {}, 节点实例ID: {}", 
                            participant.getEmployeeId(), participant.getNodeInstanceId(), ex);
                }
            }
            
            log.info("单条插入完成 - 成功: {}, 失败: {}", successCount, failCount);
        }
    }
    
    /**
     * 记录发起协商日志
     */
    private void logNegotiationLaunch(Integer contractId, Long applicantId, Long instanceId) {
        try {
            log.info("=== 开始记录发起协商日志 ===");
            log.info("参数 - 合同ID: {}, 申请人ID: {}, 流程实例ID: {}", contractId, applicantId, instanceId);
            
            // 构建日志数据
            ContractOperationLog operationLog = ContractOperationLog.builder()
                    .contractId(contractId.longValue())
                    .flowType(WorkFlowTypeEnums.NEGOTIATION_WORKFLOW.getCode())
                    .actionType(ActionTypeEnums.LAUNCH_NEGOTIATION.getCode())
                    .sourceType(SourceTypeEnums.USER.getCode())
                    .userId(applicantId)
                    .actionTime(new Date())
                    .build();
            
            // 从动态字段获取主合同文件ID（字段ID=20）
            Long mainContractFileId = getMainContractFileIdFromDynamicField(contractId);
            log.info("从动态字段查询到主合同文件ID: {}", mainContractFileId);
            
            if (mainContractFileId != null) {
                log.info("主合同文件ID不为空，开始构建扩展数据: {}", mainContractFileId);
                
                Map<String, Object> extData = new HashMap<>();
                extData.put("mainContractFileId", mainContractFileId);
                
                // 获取文件版本信息
                String version = getFileVersionInfo(contractId, mainContractFileId);
                if (version != null) {
                    extData.put("version", version);
                    log.info("添加版本信息到扩展数据: {}", version);
                } else {
                    log.info("未获取到版本信息，不添加version字段");
                }
                
                String extDataJson = JacksonUtils.toJson(extData);
                operationLog.setExtData(extDataJson);
                log.info("构建的扩展数据JSON: {}", extDataJson);
            } else {
                log.warn("主合同文件ID为空，不添加扩展数据，合同ID: {}", contractId);
            }
            
            // 保存日志
            contractOperationLogService.save(operationLog);
            log.info("记录发起协商日志成功，合同ID: {}, 流程实例ID: {}, ext_data: {}", 
                    contractId, instanceId, operationLog.getExtData());
            
        } catch (Exception e) {
            log.error("记录发起协商日志失败，合同ID: {}, 申请人ID: {}, 流程实例ID: {}", 
                    contractId, applicantId, instanceId, e);
        }
    }
    
    /**
     * 记录邀请协商者日志
     */
    private void logNegotiatorInvitation(Integer contractId, Set<Long> participantIds) {
        try {
            if (participantIds.isEmpty()) {
                log.warn("没有参与者信息，跳过邀请协商者日志记录");
                return;
            }
            
            // 构建日志数据
            ContractOperationLog operationLog = ContractOperationLog.builder()
                    .contractId(contractId.longValue())
                    .flowType(WorkFlowTypeEnums.NEGOTIATION_WORKFLOW.getCode())
                    .actionType(ActionTypeEnums.INVITE_NEGOTIATOR.getCode())
                    .sourceType(SourceTypeEnums.SYSTEM.getCode())
                    .actionTime(new Date())
                    .remark("邀请")
                    .build();
            
            // 添加参与者ID到扩展信息
            Map<String, Object> extData = new HashMap<>();
            extData.put("participantIds", participantIds);
            operationLog.setExtData(JacksonUtils.toJson(extData));
            
            // 保存日志
            contractOperationLogService.save(operationLog);
            log.info("记录邀请协商者日志成功，合同ID: {}, 参与者数量: {}", contractId, participantIds.size());
            
        } catch (Exception e) {
            log.error("记录邀请协商者日志失败", e);
        }
    }
    
    /**
     * 从节点信息中提取所有参与者ID
     */
    private Set<Long> extractAllParticipantIds(List<NodeInfo> nodeInfos) {
        Set<Long> allParticipantIds = new HashSet<>();
        for (NodeInfo nodeInfo : nodeInfos) {
            allParticipantIds.addAll(nodeInfo.getUserIds());
        }
        return allParticipantIds;
    }
    
    /**
     * 从动态字段表获取主合同文件ID
     * 
     * @param contractId 合同ID
     * @return 主合同文件ID，如果没有找到则返回null
     */
    private Long getMainContractFileIdFromDynamicField(Integer contractId) {
        try {
            ContractFieldValueEntity fieldValue = contractFieldValueMapper.selectOne(
                    new LambdaQueryWrapper<ContractFieldValueEntity>()
                            .eq(ContractFieldValueEntity::getContractId, contractId)
                            .eq(ContractFieldValueEntity::getFieldId, 20L) // 主合同文件字段ID
            );
            
            if (fieldValue != null && fieldValue.getFieldValue() != null) {
                return Long.parseLong(fieldValue.getFieldValue());
            }
            
            return null;
        } catch (Exception e) {
            log.error("从动态字段获取主合同文件ID失败，合同ID: {}", contractId, e);
            return null;
        }
    }
    
    /**
     * 获取文件版本信息
     * 
     * @param contractId 合同ID
     * @param fileId 文件ID
     * @return 版本信息，格式为"主合同 V{major_version}.{minor_version}"，如果没有找到则返回null
     */
    private String getFileVersionInfo(Integer contractId, Long fileId) {
        try {
            // 查询该文件的最高版本记录
            LambdaQueryWrapper<ContractFileEntity> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ContractFileEntity::getContractId, contractId)
                    .eq(ContractFileEntity::getFileId, fileId)
                    .orderByDesc(ContractFileEntity::getMajorVersion)
                    .orderByDesc(ContractFileEntity::getMinorVersion)
                    .last("LIMIT 1");
            
            ContractFileEntity latestVersion = contractFileService.getOne(queryWrapper);
            
            if (latestVersion != null) {
                return String.format("主合同 V%d.%d", 
                        latestVersion.getMajorVersion(), 
                        latestVersion.getMinorVersion());
            }
            
            // 如果没有版本记录，返回null
            log.info("未找到文件版本记录，不添加版本信息，合同ID: {}, 文件ID: {}", contractId, fileId);
            return null;
            
        } catch (Exception e) {
            log.error("获取文件版本信息失败，不添加版本信息，合同ID: {}, 文件ID: {}", contractId, fileId, e);
            return null;
        }
    }
    
    // 修改内部类，增加节点相关信息
    private static class NodeInfo {
        private Integer order;
        private Integer roleId;           // 在协商系统中的节点标识
        private String nodeKey;           // 审批流节点Key
        private String nodeName;          // 审批流节点名称
        private List<Long> userIds = new ArrayList<>();
        
        public Integer getOrder() { return order; }
        public void setOrder(Integer order) { this.order = order; }
        public Integer getRoleId() { return roleId; }
        public void setRoleId(Integer roleId) { this.roleId = roleId; }
        public String getNodeKey() { return nodeKey; }
        public void setNodeKey(String nodeKey) { this.nodeKey = nodeKey; }
        public String getNodeName() { return nodeName; }
        public void setNodeName(String nodeName) { this.nodeName = nodeName; }
        public List<Long> getUserIds() { return userIds; }
        public void setUserIds(List<Long> userIds) { this.userIds = userIds; }
    }
} 